﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.ServiceModel.Channels;
using System.ServiceModel;

using System.Net;
using System.Xml;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Description;
using System.Security.Cryptography;
using System.ServiceModel.Discovery;
using System.Reflection;//
using System.IO;

namespace onvif_test
{
    public partial class Form_main : Form
    {
        //也可以直接用DataTable来绑定
        DataTable dt_client = new DataTable("client_list");

        public Form_main()
        {
            InitializeComponent();
        }

        static void discoveryClient_FindProgressChanged(object sender, FindProgressChangedEventArgs e)
        {
            //Check endpoint metadata here for required types.
            System.Diagnostics.Debug.WriteLine("Found service at: " + e.EndpointDiscoveryMetadata.Address);
            return;

        }

        private void Form_main_Load(object sender, EventArgs e)
        {
            //使用DataSet绑定时，必须同时指明DateMember  
            //2.创建带列名和类型名的列(两种方式任选其一)
           
            dt_client.Columns.Add("uuid", typeof(String));
            dt_client.Columns.Add("ipV4 addr",typeof(String));
            dt_client.Columns.Add("ipV6 addr", typeof(String));
            dt_client.Columns.Add("metadata ver", typeof(String));

            return;
        }

        /// <summary>
        /// 发现局域网内设备
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_discover_Click(object sender, EventArgs e)
        {
            var endPoint = new UdpDiscoveryEndpoint(DiscoveryVersion.WSDiscoveryApril2005);
            var discoveryClient = new DiscoveryClient(endPoint);
            discoveryClient.FindProgressChanged += discoveryClient_FindProgressChanged;//添加响应事件
            FindCriteria findCriteria = new FindCriteria();
            findCriteria.MaxResults = int.MaxValue;
            // Edit: optionally specify contract type, ONVIF v1.0
            findCriteria.ContractTypeNames.Add(new XmlQualifiedName("NetworkVideoTransmitter", "http://www.onvif.org/ver10/network/wsdl"));
            //findCriteria.Duration = TimeSpan.MaxValue;
            // discoveryClient.FindAsync(findCriteria);//异步查找

            findCriteria.Duration = TimeSpan.FromSeconds(2);//同步查找2秒
            FindResponse fr = discoveryClient.Find(findCriteria);
            //EndpointAddress ep = new EndpointAddress();

            if (fr.Endpoints.Count > 0)
            {
                // dgv_client_list.
                foreach(var element in fr.Endpoints)
                {

                    dt_client.Rows.Add( element.Address,element.ListenUris[0],element.ListenUris[1],element.Version);                    
                }
                DataView dv = new DataView(dt_client);
                //dv.ToTable(true,)
               // dt_client.Clear();
                dt_client = dv.ToTable(true);


                this.dgv_client_list.DataSource = dt_client;

                //fr.Endpoints
                //System.Diagnostics.Debug.WriteLine(ep.Uri);
                //System.Diagnostics.Debug.WriteLine(ip);
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            var messageElement = new TextMessageEncodingBindingElement();
            messageElement.MessageVersion = MessageVersion.CreateVersion(EnvelopeVersion.Soap12, AddressingVersion.None);
            HttpTransportBindingElement httpBinding = new HttpTransportBindingElement();
            httpBinding.AuthenticationScheme = AuthenticationSchemes.Digest;

            CustomBinding ipc_bind = new CustomBinding(messageElement, httpBinding);

            //绑定服务地址
            EndpointAddress ipc_addr = new EndpointAddress(dt_client.Rows[0][1].ToString());
            OnvifDevice.DeviceClient deviceClient = new OnvifDevice.DeviceClient(ipc_bind, ipc_addr);
            deviceClient.ClientCredentials.HttpDigest.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Delegation;
            deviceClient.ClientCredentials.HttpDigest.ClientCredential.UserName = "admin";
            deviceClient.ClientCredentials.HttpDigest.ClientCredential.Password = "zhikong123";


            OnvifDevice.SystemDateTime dt = deviceClient.GetSystemDateAndTime();

            var ret_var = new OnvifDevice.DeviceServiceCapabilities();
            ret_var = deviceClient.GetServiceCapabilities();

            String[] out_list = new String[4];
            deviceClient.GetDeviceInformation(out out_list[0], out out_list[1], out out_list[2], out out_list[3]);
            foreach (String element in out_list)
            {
                System.Diagnostics.Debug.WriteLine(element);
            }
        }



        private void button2_Click(object sender, EventArgs e)
        {
            var messageElement = new TextMessageEncodingBindingElement();
            messageElement.MessageVersion = MessageVersion.CreateVersion(EnvelopeVersion.Soap12, AddressingVersion.None);
            HttpTransportBindingElement httpBinding = new HttpTransportBindingElement();
            httpBinding.AuthenticationScheme = AuthenticationSchemes.Digest;
            CustomBinding bind = new CustomBinding(messageElement, httpBinding);
            EndpointAddress mediaAddress = new EndpointAddress("http://192.168.0.158/onvif/Media");
            OnvifMedia.MediaClient mediaClient = new OnvifMedia.MediaClient(bind, mediaAddress);

            mediaClient.ClientCredentials.HttpDigest.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Delegation;
            mediaClient.ClientCredentials.HttpDigest.ClientCredential.UserName = "admin";
            mediaClient.ClientCredentials.HttpDigest.ClientCredential.Password = "zhikong123";
            OnvifMedia.Profile[] profiles = mediaClient.GetProfiles();
            string profileToken = profiles[3].token;

            OnvifMedia.MediaUri snapshotUri = mediaClient.GetSnapshotUri(profileToken);//获取图片地址
            HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(snapshotUri.Uri);
            req.Method = "GET";
            // Define the request credentials according to the user's input.
            req.Credentials = new NetworkCredential("admin", "zhikong123");
            // Issue the request.
            HttpWebResponse result = (HttpWebResponse)req.GetResponse();
            System.IO.Stream sm = result.GetResponseStream();
            Image image = Image.FromStream(sm);
            sm.Close();
            pictureBox1.Image = image;

            OnvifMedia.StreamSetup streamSetup = new OnvifMedia.StreamSetup();
            streamSetup.Stream = OnvifMedia.StreamType.RTPUnicast;
            streamSetup.Transport = new OnvifMedia.Transport();
            streamSetup.Transport.Protocol = OnvifMedia.TransportProtocol.RTSP;
            OnvifMedia.MediaUri streamUri = mediaClient.GetStreamUri(streamSetup, profileToken);//获取视频流地址

            //Uri uriAddress3 = new Uri(streamUri.Uri);
            //uriAddress3.UserInfo = "admin:zhikong123";

            UriBuilder uriBuilder = new UriBuilder(streamUri.Uri);
            uriBuilder.Password = "zhikong123";
            uriBuilder.UserName = "admin";

            vlcControl1.Play(uriBuilder.Uri.ToString());


            //return;

            //IntPtr render_wnd = player.Handle;
        }


        /// <summary>
        /// When the Vlc control needs to find the location of the libvlc.dll.
        /// You could have set the VlcLibDirectory in the designer, but for this sample, we are in AnyCPU mode, and we don't know the process bitness.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void vlcControl1_VlcLibDirectoryNeeded(object sender, Vlc.DotNet.Forms.VlcLibDirectoryNeededEventArgs e)
        {
            var currentAssembly = Assembly.GetEntryAssembly();
            var currentDirectory = new FileInfo(currentAssembly.Location).DirectoryName;
            // Default installation path of VideoLAN.LibVLC.Windows
            e.VlcLibDirectory = new DirectoryInfo(Path.Combine(currentDirectory, "libvlc", IntPtr.Size == 4 ? "win-x86" : "win-x64"));

            if (!e.VlcLibDirectory.Exists)
            {
                var folderBrowserDialog = new FolderBrowserDialog();
                folderBrowserDialog.Description = "Select Vlc libraries folder.";
                folderBrowserDialog.RootFolder = Environment.SpecialFolder.Desktop;
                folderBrowserDialog.ShowNewFolderButton = true;
                if (folderBrowserDialog.ShowDialog() == DialogResult.OK)
                {
                    e.VlcLibDirectory = new DirectoryInfo(folderBrowserDialog.SelectedPath);
                }
            }
        }
    }
}
